<template></template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export default {
  name: "parent-app",
  data() {
    return {};
  },
  created() {},
  mounted() {
    this.load();
  },
  methods: {
    /** 初始加载 */
    load() {
      // 创建场景对象Scene
      let scene = new THREE.Scene();
      /** --------------------物体--------------------- */
      // 物体--三角面几何
      // let geometry = {
      //   0: new THREE.BoxGeometry(100, 100, 100),
      // };
      // // 几何体xyz三个方向都放大2倍
      // geometry[0].scale(2, 2, 2);
      // // 几何体沿着x轴平移50
      // geometry[0].translate(50, 0, 0);
      // // 几何体绕着x轴旋转45度
      // geometry[0].rotateX(Math.PI / 4);
      // // 居中：偏移的几何体居中
      // geometry[0].center();
      // console.log("geometry", geometry[0]);
      // console.log("顶点", geometry[0].vertices);
      // console.log("三角面", geometry[0].faces);
      // geometry[0].faces.forEach((face) => {
      //   // 设置三角面face三个顶点的颜色
      //   face.vertexColors = [
      //     new THREE.Color(0xffff00),
      //     new THREE.Color(0xff00ff),
      //     new THREE.Color(0x00ffff),
      //   ];
      // });
      // // 顶点位置
      // let points = {
      //   0: new THREE.Vector3(0, 0, 0),
      //   1: new THREE.Vector3(0, 100, 0),
      //   2: new THREE.Vector3(50, 0, 0),
      //   3: new THREE.Vector3(0, 0, 100),
      // };
      // // 顶点坐标添加到几何对象中
      // // geometry[0].vertices.push(points[0], points[1], points[2], points[3]);

      // // 构建三角面
      // let faces = {
      //   f1: new THREE.face3(0, 1, 2),
      //   f1: new THREE.face3(0, 2, 3),
      // };
      // // 三角面的顶点法向量：一种是设置每个顶点位置的法向量，一种是设置三角形面的法向量
      // let normalVector = {
      //   n1: new THREE.Vector3(0, 0, -1),
      //   n2: new THREE.Vector3(0, 0, -1),
      //   n3: new THREE.Vector3(0, 0, -1),
      //   n4: new THREE.Vector3(0, -1, 0),
      // };
      // // 设置每个顶点位置的法向量
      // faces.f1.vertexNormaks.push(
      //   normalVector.n1,
      //   normalVector.n2,
      //   normalVector.n3
      // );
      // // 设置三角形面的法向量
      // faces.f2.normal = normalVector.n3;

      // geometry[0].faces.push(faces.f1, faces.f2);

      // // 三角面的顶点颜色：一种设置三角面的三个顶点颜色，一种是设置三角面的颜色
      // // 使用顶点颜色数据的时候，注意设置材质的属性vertexColors属性值为THREE.VertexColors。
      // let color = {
      //   0: new THREE.Color(0xffff00),
      //   1: new THREE.Color(0xff00ff),
      //   2: new THREE.Color(0x00ffff),
      // };
      // // 设置三角面的三个顶点颜色
      // faces.f1.vertexColors = [color[0],color[1],color[2]]
      // // 设置三角面的颜色
      // faces.f2.color = color[0]

      // var p1 = new THREE.Vector3(-85.35, -35.36);
      // var p2 = new THREE.Vector3(-50, 0, 0);
      // var p3 = new THREE.Vector3(0, 50, 0);
      // var p4 = new THREE.Vector3(50, 0, 0);
      // var p5 = new THREE.Vector3(85.35, -35.36);
      // // 创建线条一：直线
      // let line1 = new THREE.LineCurve3(p1, p2);
      // // 重建线条2：三维样条曲线
      // var curve = new THREE.CatmullRomCurve3([p2, p3, p4]);
      // // 创建线条3：直线
      // let line2 = new THREE.LineCurve3(p4, p5);
      // var CurvePath = new THREE.CurvePath(); // 创建CurvePath对象
      // CurvePath.curves.push(line1, curve, line2); // 插入多段线条
      // //通过多段曲线路径创建生成管道
      // //通过多段曲线路径创建生成管道，CCurvePath：管道路径
      // var geometry2 = new THREE.TubeGeometry(CurvePath, 100, 5, 25, false);
      // /** --------------------材质--------------------- */
      // // 设置材质--漫反射
      // let material = new THREE.MeshLambertMaterial({
      //   color: 0xff04ff,
      //   // vertexColors: THREE.FaceColors, //
      //   // vertexColors: THREE.VertexColors, //顶点颜色
      //   side: THREE.DoubleSide, //两面可见
      // });
      // /** --------------------实体模型--------------------- */
      // // 设置网络模型对象，实体模型
      // let mesh = new THREE.Mesh(geometry[0], material);
      // let mesh2 = new THREE.Mesh(geometry2, material);

      // // 设置产生投影的网格模型
      // mesh.castShadow = true;

      // let a = mesh.clone(); // 模型对象克隆
      // a.position.z = 300;
      // // 辅助坐标系  参数250表示坐标系大小，可以根据场景大小去设置
      // let axisHelper = new THREE.AxisHelper(250);
      // scene.add(axisHelper);
      // /** --------------------场景--------------------- */
      // // 网格模型添加到场景中
      // scene.add(mesh2);
      var geometry = new THREE.BoxGeometry(100, 100, 100); //立方体
      // var geometry = new THREE.PlaneGeometry(204, 102, 4, 4); //矩形平面
      // var geometry = new THREE.SphereGeometry(60, 25, 25); //球体
      // var geometry = new THREE.CylinderGeometry(60, 60, 25,25); //圆柱
      //
      console.log("=========geometry", geometry.faces);

      // 材质对象1
      var material_1 = new THREE.MeshPhongMaterial({
        color: 0xffff3f,
      });
      var textureLoader = new THREE.TextureLoader(); // 纹理加载器
      var texture = textureLoader.load(
        "http://static.bimface.com/attach/1c257af511aa4617b30031913d58b79b_timg.jpg"
      ); // 加载图片，返回Texture对象
      //阵列
      // 材质对象2
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.RepeatWrapping;
      // uv两个方向纹理重复数量
      texture.repeat.set(4, 3);
      //偏移
      texture.offset = new THREE.Vector2(0.3, 0.1);
      //旋转
      // 设置纹理旋转角度
      texture.rotation = Math.PI / 4;
      // 设置纹理的旋转中心，默认(0,0)
      texture.center.set(0.5, 0.5);
      var material_2 = new THREE.MeshLambertMaterial({
        map: texture, // 设置纹理贴图
        // lightMap: texture, // 设置纹理贴图
        // color: 0x999999,
        // wireframe:true,
      });
      // 设置材质数组
      var materialArr = [
        material_1,
        material_1,
        material_1,
        material_1,
        material_2,
        material_2,
      ];

      // 设置数组材质对象作为网格模型材质参数
      var mesh = new THREE.Mesh(geometry, materialArr); //网格模型对象Mesh
      let mesh2 = mesh.clone();
      mesh2.position.x = 300;
      scene.add(mesh, mesh2); //网格模型添加到场景中
      // scene.add(a);

      /** --------------------平面网格模型接收投影--------------------- */
      // 创建一个平面几何体作为投影面
      var planeGeometry = new THREE.PlaneGeometry(3000, 2000, 4, 4);
      // var planeGeometry = new THREE.SphereGeometry(300, 200, 200);
      // var planeMaterial = new THREE.MeshLambertMaterial({
      //   color: 0x999999,
      //   side: THREE.DoubleSide,
      // });
      console.log("planeGeometry===", planeGeometry.faceVertexUvs);

      // TextureLoader创建一个纹理加载器对象，可以加载图片作为几何体纹理
      var textureLoader = new THREE.ImageLoader();
      // 执行load方法，加载纹理贴图成功后，返回一个纹理对象Texture
      var texture2;
      textureLoader.load(
        "http://static.bimface.com/attach/1c257af511aa4617b30031913d58b79b_timg.jpg",
        function (img) {
          texture2 = new THREE.Texture(img);
          // 下次使用纹理时触发更新
          texture2.needsUpdate = true;
          // 设置阵列模式为 RepeatWrapping
          // texture2.wrapS = THREE.RepeatWrapping;
          // texture2.wrapT = THREE.RepeatWrapping;
          // 设置x方向的偏移(沿着管道路径方向)，y方向默认1
          //等价texture.repeat= new THREE.Vector2(20,1)
          // texture2.repeat.x = 20;
          var material = new THREE.MeshLambertMaterial({
            map: texture2, //设置纹理贴图
            side: THREE.DoubleSide,
            transparent: true,
          });
          // var material = new THREE.MeshLambertMaterial({
          //   // color: 0x0000ff,
          //   // 设置颜色纹理贴图：Texture对象作为材质map属性的属性值
          //   map: texture, //设置颜色贴图属性值
          //   side: THREE.DoubleSide,
          // }); //材质对象Material
          var planeMesh = new THREE.Mesh(planeGeometry, material); //网格模型对象Mesh
          scene.add(planeMesh); //网格模型添加到场景中
          planeMesh.rotateX(-60); //旋转网格模型
          planeMesh.position.y = -550; //设置网格模型y坐标
          // 设置接收阴影的投影面
          planeMesh.receiveShadow = true;
          //纹理贴图加载成功后，调用渲染函数执行渲染操作
          // render();
        }
      );
      // 平面网格模型作为投影面
      // var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
      // scene.add(planeMesh); //网格模型添加到场景中

      /** --------------------光源设置--------------------- */
      // //点光源
      // let pointLight = {
      //   p1: new THREE.DirectionalLight(0xfff),
      //   p2: new THREE.PointLight(0xfff),
      // };
      // pointLight.p1.position.set(400, 400, 300); //点光源位置
      // pointLight.p1.target = mesh; //点光源位置
      // // pointLight.p2.position.set(-200, -400, -300); //点光源位置
      // scene.add(pointLight.p1); //点光源添加到场景中
      // // scene.add(pointLight.p2); //点光源添加到场景中

      // 方向光
      var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
      var helper = new THREE.DirectionalLightHelper(directionalLight, 5);
      scene.add(helper);
      // 设置光源位置
      directionalLight.position.set(60, 600, 640);
      scene.add(directionalLight);
      // 设置用于计算阴影的光源对象
      directionalLight.castShadow = true;
      // 设置计算阴影的区域，最好刚好紧密包围在对象周围
      // 计算阴影的区域过大：模糊  过小：看不到或显示不完整
      directionalLight.shadow.camera.near = 0.5;
      directionalLight.shadow.camera.far = 300;
      directionalLight.shadow.camera.left = -50;
      directionalLight.shadow.camera.right = 50;
      directionalLight.shadow.camera.top = 200;
      directionalLight.shadow.camera.bottom = -100;
      // 设置mapSize属性可以使阴影更清晰，不那么模糊
      // directionalLight.shadow.mapSize.set(1024,1024)
      console.log(directionalLight.shadow.camera);
      //环境光
      let ambient = new THREE.AmbientLight(0x444444);
      scene.add(ambient);
      console.log("============scene", scene.children);

      /** --------------------相机设置--------------------- */
      let width = window.innerWidth; //窗口宽度
      let height = window.innerHeight; //窗口高度
      let k = width / height; //窗口宽高比
      let s = 300; //三维场景显示范围控制系数，系数越大，显示的范围越大
      //创建相机对象
      let camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 10000);
      // let camera = new THREE.PerspectiveCamera(120, width / height, 1, 1000);
      camera.position.set(850, 800, 800); //设置相机位置
      camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

      /** --------------------渲染器对象--------------------- */
      let renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height); //设置渲染区域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
      document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

      function render() {
        // 执行渲染操作   指定场景、相机作为参数
        renderer.render(scene, camera);
        texture && (texture.offset.x -= 0.006);
        requestAnimationFrame(render);
      }
      render();

      /** --------------------鼠标控件对象--------------------- */
      let controls = new OrbitControls(camera, renderer.domElement); //创建控件对象
      // controls.addEventListener("change", render); //监听鼠标、键盘事件
    },
  },
};
</script>

